﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using SF.Code.Extension.ComponentHelper;
using SF.Code.Extension.WinAPI.Docking;
using SG.Productivity.DesktopControlPanel.ParallelQuery;

namespace SG.Productivity.DesktopControlPanel.Controls
{
    public partial class SearchResultInfoPanel : BorderlessInfoPanel, IActivatableItemContainer<DataGridCell>
    {
        private const int MaxRows = 30;
        private const int MaxCols = 6;
        private const int ItemHeight = 40;
        private const int ItemWidth = 250;

        public SearchResultInfoPanel()
        {
            InitializeComponent();
        }

        public void AdjustInfoPanel(int collapsedDiff)
        {
            var infoPanelBounds = Bounds;
            infoPanelBounds.Offset(0, collapsedDiff);
            infoPanelBounds.Width = ItemWidth * Math.Max(1, MaxCols / 2);
            infoPanelBounds.Height = ItemHeight * Math.Max(1, MaxRows / 4);
            Bounds = infoPanelBounds;

            if (this.CheckDesignMode()) return;

            var controls = MatchControls;
            var size = new Size(ItemWidth, ItemHeight);
            for (var col = 0; col < MaxCols; col++)
            {
                for (var row = 0; row < MaxRows; row++)
                {
                    var control = new QueryMatchControl
                        {
                            Location = new Point(ItemWidth*col, ItemHeight*row),
                            Visible = false,
                            Tag = new DataGridCell(row, col),
                            MinimumSize = size,
                            MaximumSize = size,
                            Size = size
                        };
                    control.RequestActivation += QueryMatchControlRequestActivation;
                    control.LinkClicked += QueryMatchControlOnLinkClicked;
                    controls.Add(control);
                }
            }
        }

        void QueryMatchControlOnLinkClicked(object sender, LinkLabelLinkClickedEventArgs linkLabelLinkClickedEventArgs)
        {
            ReturnToCaller();
        }

        void QueryMatchControlRequestActivation(object sender, RequestActivationEventArgs e)
        {
            var control = (Control) sender;
            var index = (DataGridCell)(control.Tag);
            ActivateItem(index);
        }

        private DataGridCell? _activatedItem;

        public void ActivateItem(DataGridCell cell)
        {
            if (_activatedItem.HasValue && cell.Equals(_activatedItem.Value))
                return;

            if (cell.RowNumber == 0)
                SetVisibility(activate: PanelActivation.Callee);

            var controls = MatchControls;
            if (cell.RowNumber < 0)
            {
                _activatedItem = null;
                SetVisibility(activate: PanelActivation.Caller);
            }
            else if (controls.Count > 0)
            {
                var current = new DataGridCell(Math.Min(cell.RowNumber, Math.Max(0, controls.Count - 1)), cell.ColumnNumber);
                if (!this[current].Visible)
                    return;

                if (_activatedItem.HasValue)
                    SetActiveMatchResult(_activatedItem.Value, false);

                SetActiveMatchResult(current, true);
                _activatedItem = current;
            }
        }

        private void SetActiveMatchResult(DataGridCell current, bool active)
        {
            this[current].SetActive(active);
        }

        private Control.ControlCollection MatchControls
        {
            get { return Controls; }
        }

        public void MergeOrderAndDisplayResults(QueryIdentifier identifier, IEnumerable<QueryMatch> updatedRecordList)
        {
            var mergedRecords = new List<QueryMatch>( (int) (_numberOfItems * 1.7f) + 1);
            mergedRecords.Capacity = mergedRecords.Count + _numberOfItems;

            const int TODO = 0;
            for (var i = 0; i < _numberOfItems; i++)
            {
                var comparand = this[new DataGridCell(i, TODO)];
                if (comparand.Identifier.Query == identifier.Query)
                    continue;
                
                mergedRecords.Add(comparand.Match);
            }
            
            mergedRecords.AddRange(updatedRecordList);

            ClearAndDisplayResults(identifier, mergedRecords.OrderByDescending(pMatch => pMatch != null ? pMatch.Weight : 0.1).Take(MaxRows));
        }

        private int _numberOfItems;
        private void ClearAndDisplayResults(QueryIdentifier identifier, IEnumerable<QueryMatch> orderedRecords)
        {
            SuspendLayout();

            var recordIndex = 0;
            foreach (var record in orderedRecords)
                UpdateMatch(identifier, recordIndex++, record);

            _numberOfItems = recordIndex;

            var matchControls = MatchControls;

            for (var i = _numberOfItems; i < matchControls.Count; i++)
            {
                var control = matchControls[i];
                if (!control.Visible)
                    break;

                control.Visible = false;
            }

            //SetHeightIfDiffer(_numberOfItems*ItemHeight);

            ResumeLayout(true);
        }

        private void SetHeightIfDiffer(int newHeight)
        {
            var previousHeight = Height;

            if (previousHeight != newHeight)
            {
                MinimumSize = new Size(MinimumSize.Width, newHeight);
                MaximumSize = new Size(MaximumSize.Width, newHeight);
                Height = newHeight;
            }
        }

        protected override bool OnSpecialKey(Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Up:
                case Keys.Down:
                    if (!_activatedItem.HasValue)
                        goto default;

                    if (IsLogicalDown(keyData))
                    {
                        ActivateItem(_activatedItem.Value.ReduceRow());
                        return true;
                    }
                    if (IsLogicalUp(keyData))
                    {
                        ActivateItem(_activatedItem.Value.IncreaseRow());
                        return true;
                    }
                    return false;


                default:
                    return false;
            }
        }

        private bool IsLogicalUp(Keys keyData)
        {
            return SpecialKeySet.ShowKey.HasFlag(keyData);
        }

        private bool IsLogicalDown(Keys keyData)
        {
            return SpecialKeySet.BackKey.HasFlag(keyData);
        }
        
        public void UpdateMatch(QueryIdentifier identifier, int i, QueryMatch match)
        {
            return;
            /*
            var control = this[i];
            control.Identifier = identifier;
            control.Match = match;
            control.Show();
             */
        }

        private bool TryGetControl(QueryMatch match, out QueryMatchControl control)
        {
            var found = MatchControls.Find(match.Uri.ToString(), false);
            var success = found.Length == 1 && found[0] as QueryMatchControl != null;

            control = success ? (QueryMatchControl) found[0] : null;

            return success;
        }
        private QueryMatchControl this[DataGridCell cell]
        {
            get { return (QueryMatchControl) MatchControls[(cell.ColumnNumber * MaxRows) + cell.RowNumber]; }
        }
    }
}
